# -*- coding: utf-8 -*-
"""
管理员管理模块 - 权限控制系统

本文件实现了测试DEMO中基于角色的访问控制(RBAC)权限系统，包括：

1. 权限检查类：
   - IsAdminUser: 检查用户是否为管理员
   - HasPermission: 检查用户是否具有特定权限
   - IsSuperAdmin: 检查用户是否为超级管理员
   - CanManageUsers: 检查用户是否可以管理其他用户
   - CanManageRoles: 检查用户是否可以管理角色
   - CanViewAuditLogs: 检查用户是否可以查看审计日志
   - RoleBasedPermission: 基于角色的权限检查

2. 权限装饰器和混入类：
   - PermissionRequiredMixin: 权限检查混入类
   - permission_required: 权限要求装饰器
   - role_required: 角色要求装饰器

3. 权限检查工具类：
   - PermissionChecker: 权限检查工具类
     * has_permission: 检查用户权限
     * has_role: 检查用户角色
     * get_user_permissions: 获取用户权限列表
     * get_user_roles: 获取用户角色列表

4. 权限和角色常量定义：
   - Permissions: 系统权限常量定义
     * 用户管理权限 (USER_*)
     * 产品管理权限 (PRODUCT_*)
     * 投资管理权限 (INVESTMENT_*)
     * 分析报告权限 (ANALYTICS_*)
     * 系统管理权限 (SYSTEM_*)
     * 监控管理权限 (MONITORING_*)
     * 安全管理权限 (SECURITY_*)
   - Roles: 系统角色常量定义
     * 超级管理员 (SUPER_ADMIN)
     * 系统管理员 (ADMIN)
     * 理财顾问 (FINANCIAL_ADVISOR)
     * 分析师 (ANALYST)
     * 操作员 (OPERATOR)

该权限系统支持细粒度的权限控制，确保不同角色的用户只能访问
其被授权的功能和数据，保障系统的安全性。

Author: zhaozeliang
Date: 2025-09-06
"""

from rest_framework import permissions  # type: ignore
from rest_framework.exceptions import PermissionDenied  # type: ignore
from django.contrib.auth.models import User  # type: ignore
from .models import AdminUser, Role, Permission


class IsAdminUser(permissions.BasePermission):
    """
    自定义权限：检查用户是否为管理员
    """
    
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        try:
            admin_user = AdminUser.objects.get(user=request.user)
            return admin_user.is_active
        except AdminUser.DoesNotExist:
            return False


class HasPermission(permissions.BasePermission):
    """
    自定义权限：检查用户是否具有特定权限
    """
    
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        # 获取视图所需的权限
        required_permissions = getattr(view, 'required_permissions', {})
        action = view.action or 'list'
        required_permission = required_permissions.get(action)
        
        if not required_permission:
            return True  # 如果没有定义权限要求，则允许访问
        
        return self.user_has_permission(request.user, required_permission)
    
    def user_has_permission(self, user, permission_code):
        """
        检查用户是否具有指定权限
        """
        try:
            from .models import UserRole, RolePermission
            admin_user = AdminUser.objects.get(user=user)
            if not admin_user.is_active:
                return False
            
            # 检查用户角色是否具有所需权限
            user_permissions = Permission.objects.filter(
                permission_roles__role__role_users__user=user,
                permission_roles__role__role_users__is_active=True
            ).values_list('code', flat=True)
            
            return permission_code in user_permissions
        except AdminUser.DoesNotExist:
            return False
        except Exception:
            return False


class IsSuperAdmin(permissions.BasePermission):
    """
    自定义权限：检查用户是否为超级管理员
    """
    
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        try:
            admin_user = AdminUser.objects.get(user=request.user)
            return admin_user.is_active and admin_user.is_super_admin
        except AdminUser.DoesNotExist:
            return False


class CanManageUsers(permissions.BasePermission):
    """
    自定义权限：检查用户是否可以管理其他用户
    """
    
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        return HasPermission().user_has_permission(request.user, 'user_management:manage')


class CanManageRoles(permissions.BasePermission):
    """
    自定义权限：检查用户是否可以管理角色
    """
    
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        return HasPermission().user_has_permission(request.user, 'role:manage')


class CanViewAuditLogs(permissions.BasePermission):
    """
    自定义权限：检查用户是否可以查看审计日志
    """
    
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        return HasPermission().user_has_permission(request.user, 'audit_log:read')


class RoleBasedPermission(permissions.BasePermission):
    """
    基于角色的权限检查
    """
    
    def __init__(self, required_roles=None):
        self.required_roles = required_roles or []
    
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        try:
            admin_user = AdminUser.objects.get(user=request.user)
            if not admin_user.is_active:
                return False
            
            # 检查用户是否具有所需角色
            user_roles = admin_user.roles.values_list('name', flat=True)
            
            # 如果没有指定所需角色，则只检查是否为管理员
            if not self.required_roles:
                return True
            
            # 检查是否具有任一所需角色
            return any(role in user_roles for role in self.required_roles)
        except AdminUser.DoesNotExist:
            return False


class PermissionRequiredMixin:
    """
    权限检查混入类，用于视图类
    """
    permission_required = None
    
    def check_permissions(self, request):
        """
        检查用户权限
        """
        if not self.permission_required:
            return True
        
        if not request.user or not request.user.is_authenticated:
            raise PermissionDenied("用户未认证")
        
        try:
            admin_user = AdminUser.objects.get(user=request.user)
            if not admin_user.is_active:
                raise PermissionDenied("管理员账户已被禁用")
            
            # 检查权限
            user_permissions = Permission.objects.filter(
                roles__adminuser=admin_user
            ).values_list('code', flat=True)
            
            if isinstance(self.permission_required, str):
                required_perms = [self.permission_required]
            else:
                required_perms = self.permission_required
            
            for perm in required_perms:
                if perm not in user_permissions:
                    raise PermissionDenied(f"缺少权限: {perm}")
            
            return True
        except AdminUser.DoesNotExist:
            raise PermissionDenied("用户不是管理员")
    
    def dispatch(self, request, *args, **kwargs):
        self.check_permissions(request)
        return super().dispatch(request, *args, **kwargs)


def permission_required(permission_codes):
    """
    权限装饰器
    """
    def decorator(view_func):
        def wrapper(request, *args, **kwargs):
            if not request.user or not request.user.is_authenticated:
                raise PermissionDenied("用户未认证")
            
            try:
                admin_user = AdminUser.objects.get(user=request.user)
                if not admin_user.is_active:
                    raise PermissionDenied("管理员账户已被禁用")
                
                # 检查权限
                user_permissions = Permission.objects.filter(
                    roles__adminuser=admin_user
                ).values_list('code', flat=True)
                
                if isinstance(permission_codes, str):
                    required_perms = [permission_codes]
                else:
                    required_perms = permission_codes
                
                for perm in required_perms:
                    if perm not in user_permissions:
                        raise PermissionDenied(f"缺少权限: {perm}")
                
                return view_func(request, *args, **kwargs)
            except AdminUser.DoesNotExist:
                raise PermissionDenied("用户不是管理员")
        
        return wrapper
    return decorator


def role_required(role_names):
    """
    角色装饰器
    """
    def decorator(view_func):
        def wrapper(request, *args, **kwargs):
            if not request.user or not request.user.is_authenticated:
                raise PermissionDenied("用户未认证")
            
            try:
                admin_user = AdminUser.objects.get(user=request.user)
                if not admin_user.is_active:
                    raise PermissionDenied("管理员账户已被禁用")
                
                # 检查角色
                user_roles = admin_user.roles.values_list('name', flat=True)
                
                if isinstance(role_names, str):
                    required_roles = [role_names]
                else:
                    required_roles = role_names
                
                if not any(role in user_roles for role in required_roles):
                    raise PermissionDenied(f"缺少角色: {', '.join(required_roles)}")
                
                return view_func(request, *args, **kwargs)
            except AdminUser.DoesNotExist:
                raise PermissionDenied("用户不是管理员")
        
        return wrapper
    return decorator


class PermissionChecker:
    """
    权限检查工具类
    """
    
    @staticmethod
    def has_permission(user, permission_code):
        """
        检查用户是否具有指定权限
        """
        if not user or not user.is_authenticated:
            return False
        
        try:
            admin_user = AdminUser.objects.get(user=user)
            if not admin_user.is_active:
                return False
            
            user_permissions = Permission.objects.filter(
                roles__adminuser=admin_user
            ).values_list('code', flat=True)
            
            return permission_code in user_permissions
        except AdminUser.DoesNotExist:
            return False
    
    @staticmethod
    def has_role(user, role_name):
        """
        检查用户是否具有指定角色
        """
        if not user or not user.is_authenticated:
            return False
        
        try:
            admin_user = AdminUser.objects.get(user=user)
            if not admin_user.is_active:
                return False
            
            user_roles = admin_user.roles.values_list('name', flat=True)
            return role_name in user_roles
        except AdminUser.DoesNotExist:
            return False
    
    @staticmethod
    def get_user_permissions(user):
        """
        获取用户所有权限
        """
        if not user or not user.is_authenticated:
            return []
        
        try:
            admin_user = AdminUser.objects.get(user=user)
            if not admin_user.is_active:
                return []
            
            return Permission.objects.filter(
                roles__adminuser=admin_user
            ).values_list('code', flat=True)
        except AdminUser.DoesNotExist:
            return []
    
    @staticmethod
    def get_user_roles(user):
        """
        获取用户所有角色
        """
        if not user or not user.is_authenticated:
            return []
        
        try:
            admin_user = AdminUser.objects.get(user=user)
            if not admin_user.is_active:
                return []
            
            return admin_user.roles.values_list('name', flat=True)
        except AdminUser.DoesNotExist:
            return []


# 预定义权限常量
class Permissions:
    # 用户管理权限
    USER_VIEW = 'user.view'
    USER_CREATE = 'user.create'
    USER_EDIT = 'user.edit'
    USER_DELETE = 'user.delete'
    
    # 产品管理权限
    PRODUCT_VIEW = 'product.view'
    PRODUCT_CREATE = 'product.create'
    PRODUCT_EDIT = 'product.edit'
    PRODUCT_DELETE = 'product.delete'
    
    # 投资管理权限
    INVESTMENT_VIEW = 'investment.view'
    INVESTMENT_CREATE = 'investment.create'
    INVESTMENT_EDIT = 'investment.edit'
    INVESTMENT_DELETE = 'investment.delete'
    
    # 数据分析权限
    ANALYTICS_VIEW = 'analytics.view'
    ANALYTICS_EXPORT = 'analytics.export'
    
    # 系统管理权限
    SYSTEM_CONFIG = 'system.config'
    SYSTEM_BACKUP = 'system.backup'
    SYSTEM_LOG = 'system.log'
    
    # 监控权限
    MONITORING_VIEW = 'monitoring.view'
    MONITORING_MANAGE = 'monitoring.manage'
    
    # 安全权限
    SECURITY_VIEW = 'security.view'
    SECURITY_MANAGE = 'security.manage'
    
    # 超级管理员权限
    SUPER_ADMIN = 'super.admin'


# 预定义角色常量
class Roles:
    SUPER_ADMIN = 'super_admin'
    ADMIN = 'admin'
    FINANCIAL_ADVISOR = 'financial_advisor'
    ANALYST = 'analyst'
    OPERATOR = 'operator'